import App from "./App";
import Component from "./Component";
import Context from "./Context";
import IPrefable from "./reflect/IPrefable";
import BlockInputEvents = cc.BlockInputEvents;

const {ccclass, property} = cc._decorator;
/**
 * 程序常规窗口管理层. 场景中的所有层都在此管理.
 */

@ccclass
export default abstract class AbsWindow extends Component implements IPrefable {

    protected get context(): Context {
        return this._context;
    }

    // 设置背景是否允许穿透. true = 禁止穿透.false=允许穿透.  default :true
    protected set bgClickable(v: boolean) {
        this._touchBgEnable = v;
    }

    public readonly path: string;
    public readonly winName: string;

    @property(cc.Node)
    protected background: cc.Node = null;

    @property(cc.Node)
    protected contentView: cc.Node = null;

    // 是否使用显隐动画.如果不需要动画,则可以在onShow里进行修改值.
    protected useShowAnimation: boolean = true;
    protected useHideAnimation: boolean = true;

    private _isShowing: boolean = false;

    private _touchBgEnable: boolean = true;

    // 窗口context. 同一个场景下的Window 同Context.
    private _context: Context = null;

    private arguments: any = {};

    // Window初始化,不要手动调用.
    public setup(app: App) {
        this._context = app.context;
        if (this.contentView) {
            this.contentView.opacity = 0;
        }
    }

    // 启动界面时可以传递一些参数.
    public setArguments(args: any) {
        this.arguments = args;
    }

    public getArguments(): any {
        return this.arguments || {};
    }

    public getBackground(): cc.Node {
        return this.background;
    }

    public getContentView(): cc.Node {
        return this.contentView;
    }

    public isShowing(): boolean {
        return this._isShowing;
    }

    // 显示隐藏当前窗口.一般需要动画支撑.
    public async show() {
        if (this._isShowing) {
            this.node.active = true;
            if (this.contentView) {
                this.contentView.opacity = 255;
            }
            return;
        }
        this.node.active = true;
        if (this.contentView) {
            this.contentView.opacity = 255;
            this.contentView.scale = 1;
            await this.beforeShowing();
        }
        this._isShowing = true;
    }

    // 隐藏窗口,并不销毁.
    public async hide() {
        if (!this._isShowing) {
            this.node.active = false;
            return;
        }
        if (this.contentView) {
            await this.beforeHiding();
        }
        this._isShowing = false;
        this.node.active = false;
    }

    public async finish() {
        await this.hide();
        this.node.removeFromParent(true);
        this.destroy();
        return this.winName;
    }

    // 添加到节点时会执行. 考虑复用逻辑,应当放在enable中.
    public onShow() {
        this.setContentBubble(false);
        this.onStart();
        if (this.background) {
            this.setClickListenerAnim(this.background, false, (ev) => {
                this.onBgClick(ev);
            });
        }
    }

    // window 需要主动销毁.否则还是会在节点上挂载.
    public onHide() {
        this.onStop();
    }

    protected setContentBubble(bubbleEnable: boolean) {
        if (bubbleEnable) {
            if (this.contentView) {
                this.contentView.removeComponent(BlockInputEvents);
            }
        } else {
            if (this.contentView) {
                this.contentView.addComponent(BlockInputEvents);
            }
        }
    }

    protected onStart() {
    }

    protected onStop() {
    }

    // 窗口重写此方法即可增加显隐动画.
    protected async beforeShowing() {
        if (this.useShowAnimation) {
            if (!this.contentView) {
                return;
            }
            this.contentView.opacity = 0;
            // this.contentView.stopAllActions();
            return new Promise(resolve => {
                this.contentView.runAction(cc.sequence(cc.fadeIn(0.5), cc.callFunc(() => {
                    resolve();
                })));
            })
        }
    }

    protected async beforeHiding() {
        if (this.useShowAnimation) {
            if (!this.contentView) {
                return;
            }
            // this.contentView.stopAllActions();
            return new Promise(resolve => {
                this.contentView.runAction(cc.sequence(cc.fadeOut(0.5), cc.callFunc(() => {
                    resolve();
                })));
            })
        }
    }

    protected onBgClick(ev: cc.Event) {
        if (!this._touchBgEnable) {
            ev.stopPropagation();
        }
    }
}
